package cz.muni.fi.pb138.bookinfo;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.google.api.services.books.model.Volume;

import cz.muni.fi.pb138.bookinfo.R.drawable;

public class Launcher extends Activity {
	private Button ok;
	private Button info;
	private Button review;
	private Button availability;
	private Button help;
	private Button authors;
	private Button expl;
	private Button camera;
	private static String pathToImg;
	private ProgressDialog progDialog;
	private String title;
	private List<String> bookauthors = new ArrayList<String>();
	private Double rating;
	private String description;
	private URL breview;
	private List<String> reviews = new ArrayList<String>();
	private List<String> libraries = new ArrayList<String>();
	private boolean notOnGoogle;
	private boolean errorWhenScanning;
	private boolean isbnFromCamera;
	private String barcode = null;	
	
	final Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			Bundle t = msg.getData();
			libraries.addAll(t.getStringArrayList("lib"));
		}
	};

	/** Called when the activity is first created. 
	 * 
	 *  Creates listeners on all buttons and calls the searching classes to find all
	 *  needed information about book.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.launcher);

		expl = (Button) findViewById(R.id.explorer);
		ok = (Button) findViewById(R.id.ok);
		info = (Button) findViewById(R.id.info);
		review = (Button) findViewById(R.id.review);
		availability = (Button) findViewById(R.id.availability);
		help = (Button) findViewById(R.id.help);
		authors = (Button) findViewById(R.id.authors);
		camera = (Button) findViewById(R.id.camera);

		if (!isConnected(this)) {
			new AlertDialog.Builder(Launcher.this)
					.setTitle(R.string.noconnection).setIcon(drawable.alert64)
					.setMessage(R.string.noconnalert)
					.setPositiveButton("OK", null).show();
		}

		expl.setOnClickListener(new View.OnClickListener() {

			public void onClick(View v) {
				startActivity(new Intent(Launcher.this, FileDialog.class));
			}
		});

		ok.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {				
				if (isConnected(this)) { 	
					libraries.clear();
					reviews.clear();
					try {
						if(!isbnFromCamera) {
							if(pathToImg != null && !pathToImg.isEmpty()){
								barcode = scanImage();
							} else {
								new AlertDialog.Builder(Launcher.this)
								.setTitle(R.string.nopath)
								.setIcon(drawable.alert64)
								.setMessage(R.string.nopathalert)
								.setPositiveButton("OK", null).show();
								return;
							}
						}
					} catch(Exception e) {
						errorWhenScanning = true;
						
						new AlertDialog.Builder(Launcher.this)
						.setTitle(R.string.scanerr)
						.setIcon(drawable.alert64)
						.setMessage("Cannot find barcode on the photo.")
						.setPositiveButton("OK", null).show();												
						
						info.setEnabled(false);
						review.setEnabled(false);
						availability.setEnabled(false);
					}
					
					if (barcode != null) {
						try {
							BookInformationSearcher bookInfo = new BookInformationSearcherImpl();
							Volume volume = bookInfo.searchForBook(barcode);
							if (volume != null) {
								bookauthors = bookInfo.bookAuthors(volume);
								description = bookInfo.bookDescription(volume);
								rating = bookInfo.bookRating(volume);
								title = bookInfo.bookTitle(volume);
								breview = bookInfo.reviewURL(volume);								
								reviews = bookInfo.getReviews(breview);
								info.setEnabled(true);
								review.setEnabled(true);
							} else {
								notOnGoogle = true;
							}
						} catch (Exception e) {
							progDialog.dismiss();
							new AlertDialog.Builder(Launcher.this)
									.setTitle(R.string.parsererr)
									.setIcon(drawable.alert64)
									.setMessage("During retrieving the information about book occured this error: \n"
													+ e)
									.setPositiveButton("OK", null).show();								
						}
						
						if(!errorWhenScanning) {	
							final String bc = barcode;
							
							progDialog = ProgressDialog.show(Launcher.this, "",
									"Loading. Please wait...", true);
							progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
							progDialog.show();
							
							handler.postDelayed(new Runnable() {
								public void run() {
									JIBsearch search = new JIBsearch();
									List<String> lib = new ArrayList<String>();
									
									try { 
										Set<String> lb = search.retrieveLibraries(bc, title);
										System.out.println(lb.toString());
										lib.addAll(lb);

										Message msg = new Message();							
										Bundle b = new Bundle();
										b.putStringArrayList("lib",(ArrayList<String>) lib);
										msg.setData(b);														
									
										handler.sendMessage(msg);
										progDialog.dismiss();
									} catch(ServiceFailureException e) {
										progDialog.dismiss();
										new AlertDialog.Builder(Launcher.this)
										.setTitle(R.string.noconnection).setIcon(drawable.alert64)
										.setMessage(R.string.noconnalert)
										.setPositiveButton("OK", null).show();
									}									
									
									if(notOnGoogle == true) {
										info.setEnabled(false);
										review.setEnabled(false);
										
										new AlertDialog.Builder(Launcher.this)
										.setTitle(R.string.nobook)
										.setIcon(drawable.alert64)
										.setMessage(R.string.nobookerr)
										.setPositiveButton("OK", null).show();
										
										notOnGoogle = false;							
									}														
								}
							}, 10000);
							availability.setEnabled(true);						
						}
					}
										
					errorWhenScanning = false;
					isbnFromCamera = false;
					expl.setEnabled(true);
				}				
				
				if (!isConnected(this)) {
					new AlertDialog.Builder(Launcher.this)
							.setTitle(R.string.noconnection).setIcon(drawable.alert64)
							.setMessage(R.string.noconnalert)
							.setPositiveButton("OK", null).show();
				}
				
				
			}
		});

		info.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				Intent intent = new Intent(Launcher.this, Info.class);
				intent.putExtra("title", getBookTitle());
				Bundle data = new Bundle();
				data.putStringArrayList("authors", (ArrayList<String>) getBookAuthors());
				intent.putExtra("authors", data);
				intent.putExtra("rating", getBookRating());
				intent.putExtra("description", getBookDescription());
				startActivity(intent);
			}
		});

		review.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				Intent intent = new Intent(Launcher.this, Review.class);
				Bundle data = new Bundle();
				data.putStringArrayList("reviews", (ArrayList<String>) getBookReviews());
				intent.putExtra("reviews", data);
				startActivity(intent);
			}			
		});

		availability.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				Bundle data = new Bundle();
				data.putStringArrayList("list", (ArrayList<String>) libraries);
				Intent intent = new Intent(Launcher.this, Availability.class);
				intent.putExtras(data);
				startActivity(intent);
			}
		});

		help.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				startActivity(new Intent(Launcher.this, Help.class));
			}
		});

		authors.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if (!isConnected(this)) {
					new AlertDialog.Builder(Launcher.this)
							.setTitle(R.string.noconnection)
							.setIcon(drawable.alert64)
							.setMessage(R.string.noconnalert)
							.setPositiveButton("OK", null).show();
				} else {
					startActivity(new Intent(Launcher.this, Authors.class));
				}
			}
		});

		camera.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if (hasCamera()) {
					startZXingCamera(this);
				} else {
					new AlertDialog.Builder(Launcher.this)
							.setTitle(R.string.nocamera)
							.setIcon(drawable.alert64)
							.setMessage(R.string.nocamalert)
							.setPositiveButton("OK", null).show();
				}
			}
		});
	}

	/**
	 * Launch camera to scan barcode.
	 * 
	 * @param onClickListener Listener from which is method called
	 */
	public void startZXingCamera(OnClickListener onClickListener) {
		IntentIntegrator integrator = new IntentIntegrator(this);
		integrator.initiateScan();
	}
	
	/**
	 * Sets ISBN of scanned barcode.
	 */
	protected void onActivityResult(int requestCode, int resultCode,
			Intent intent) {
		IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
		if (scanResult != null && scanResult.getContents() != null) {
			isbnFromCamera = true;
			expl.setEnabled(false);
		    barcode = scanResult.getContents();
		}
	}

	/**
	 * Determines whether there is a connection to the Internet.
	 * 
	 * @param context Context on which is connection searched
	 * @return true if the device is connected to the Internet, false otherwise
	 */
	private static boolean isConnected(Context context) {
		ConnectivityManager connectivityManager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = null;
		if (connectivityManager != null) {
			networkInfo = connectivityManager
					.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		}
		return networkInfo == null ? false : networkInfo.isConnected();
	}

	/**
	 * Calls isConnected method. Created only for determination of connection
	 * from listeners.
	 * 
	 * @param onClickListener Listener from which we want to determine whether there is a connection
	 * @return result of isConnected method
	 */
	protected boolean isConnected(OnClickListener onClickListener) {
		return isConnected(this);
	}

	/**
	 * Sets path of image.
	 * 
	 * @param path Path to image
	 */
	public void setPathToImg(String path) {
		pathToImg = path;
	}

	/**
	 * Determines whether there is a camera on device.
	 * 
	 * @return true if the camera device is founded, false otherwise
	 */
	public boolean hasCamera() {
		if (this.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_CAMERA)) {
			return true;
		}
		return false;
	}

	/**
	 * Scan image to find the ISBN of book.
	 * 
	 * @return ISBN from barcode 
	 */
	private String scanImage() throws Exception {
			BarcodeScanner scanner = new BarcodeScanner();
			String isbn = scanner.decode(pathToImg);
			return isbn;
	}

	/**
	 * Gets the book's title.
	 * 
	 * @return title of book
	 */
	public String getBookTitle() {
		if (title != null) {
			return title;
		}
		return "No title found";
	}

	/**
	 * Gets the book's authors.
	 * 
	 * @return authors of book
	 */
	public List<String> getBookAuthors() {
		if (bookauthors != null) {
			return bookauthors;
		}
		return new ArrayList<String>();
	}

	/**
	 * Gets the book's description.
	 * 
	 * @return description of book
	 */
	public String getBookDescription() {
		if (description != null) {
			return description;
		}
		return "No description found";
	}

	/**
	 * Gets the book's rating.
	 * 
	 * @return rating of book
	 */
	public Double getBookRating() {
		if (rating != null) {
			return rating;
		}
		return null;
	}

	/**
	 * Gets the URL of review.
	 * 
	 * @return URL of review
	 */
	public URL getBookReview() {
		return breview;
	}
	
	/**
	 * Gets the book's reviews. 
	 * 
	 * @return reviews of book
	 */
	public List<String> getBookReviews() {
		return reviews;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.mspath:
			if (pathToImg != null && !pathToImg.isEmpty()) {
				Toast.makeText(Launcher.this, pathToImg, 4000).show();
			} else {
				Toast.makeText(Launcher.this, "PATH NOT SELECTED!", 4000)
						.show();
			}
			return true;

		default:
			return super.onOptionsItemSelected(item);
		}
	}

}